#include "dump_packet.h"

struct sockaddr_in src_addr;
struct sockaddr_in dst_addr;



void dump_ethernet_header( unsigned char *buffer, int sz)
{
    struct ethhdr *eth = (struct ethhdr *) buffer;

    fprintf( log_file, "\n" );
    fprintf( log_file, "Ethernet Header\n" );
    fprintf( log_file, " |-Dest Mac: %.2X-%.2X-%.2X-%.2X-%.2X-%.2X \n", 
		    eth->h_dest[0], eth->h_dest[1], eth->h_dest[2],
		    eth->h_dest[3], eth->h_dest[4], eth->h_dest[5]);

    fprintf( log_file, " |-Src Mac: %.2X-%.2X-%.2X-%.2X-%.2X-%.2X \n", 
		    eth->h_source[0], eth->h_source[1], eth->h_source[2],
		    eth->h_source[3], eth->h_source[4], eth->h_source[5]);


}



void dump_ip_header( unsigned char *buffer, int sz)
{
    struct iphdr *iph = (struct iphdr *) buffer;
    int ip_hdr_len = iph->ihl << 2;

    memset( &src_addr, 0, sizeof(src_addr));
    memset( &dst_addr, 0, sizeof(dst_addr));
    
    src_addr.sin_addr.s_addr = iph->saddr;
    dst_addr.sin_addr.s_addr = iph->daddr;

    fprintf(log_file,"\n");
    fprintf(log_file,"IP Header\n");
    fprintf(log_file,"source IP: %s\n",inet_ntoa(src_addr.sin_addr));
    fprintf(log_file,"dst    IP: %s\n",inet_ntoa(dst_addr.sin_addr));

}

void dump_icmp_packet( unsigned char *buffer, int sz)
{
    unsigned short ip_hdr_len;

    struct iphdr *iph = (struct iphdr *) buffer;
     ip_hdr_len = iph->ihl << 2;

    struct icmphdr *icmph = (struct icmphdr *)(buffer + ip_hdr_len);

    fprintf(log_file,"\n\n***ICMP Packet***\n");

    dump_ip_header(buffer, sz);

    fprintf(log_file,"\nICMP Header\n");
    fprintf(log_file,"  |-Type : %d", (unsigned int)(icmph->type));

    if ((unsigned int)(icmph->type) == 11)
	    fprintf(log_file," (TTL Expired)\n");
    else if ((unsigned int)(icmph->type) == ICMP_ECHOREPLY)
	    fprintf(log_file," (ICMP Echo Reply)\n");

}

void dump_udp_packet( unsigned char *buffer, int sz)
{
    
    unsigned short ip_hdr_len;

    struct iphdr *iph = (struct iphdr *) buffer;
    ip_hdr_len = iph->ihl << 2;
    
    fprintf(log_file,"***Udp Packet***\n");

    dump_ip_header(buffer, sz );

    struct udphdr *udph = (struct udphdr *)(buffer + ip_hdr_len );
    fprintf(log_file,"\n\n*** UDP Header***\n");
    
    fprintf(log_file,"  |-Src Port : %u\n", ntohs(udph->source));
    fprintf(log_file,"  |-Dst Port : %u\n", ntohs(udph->dest));
    fprintf(log_file,"  |-UDP Length: %d\n",ntohs(udph->len));
    fprintf(log_file,"  |-UDP Checksum: %d\n",ntohs(udph->check));
    
    dump_payload( buffer + ip_hdr_len + sizeof udph, sz - ip_hdr_len - sizeof udph );
}

void dump_tcp_packet( unsigned char *buffer, int sz)
{
    unsigned short ip_hdr_len;
    
    struct iphdr *iph = (struct iphdr *) buffer;
    ip_hdr_len = iph->ihl << 2;

    struct tcphdr *tcph = (struct tcphdr *)(buffer + ip_hdr_len );

    fprintf(log_file,"\n\n***TCP Packet***\n");

    dump_ip_header(log_file, sz);

    fprintf(log_file, "\nTCP Header\n");
    fprintf(log_file, "  |-Src Port : %d\n", ntohs(tcph->source));
    fprintf(log_file, "  |-Dst Port : %d\n", ntohs(tcph->dest));

    fprintf(log_file, " Seq number: %u\n", ntohl(tcph->seq));
    fprintf(log_file, " Ack number: %u\n", ntohl(tcph->ack_seq));
    fprintf(log_file, " Checksum  : %d\n", ntohs(tcph->check));

    dump_payload( buffer + ip_hdr_len + sizeof tcph, sz - ip_hdr_len - sizeof tcph );
}

void dump_payload( unsigned char *buffer, int sz)
{
    int CHARS_PER_LINE = 16;

    for (int i = 0;i < sz + CHARS_PER_LINE - 1; i += CHARS_PER_LINE ) {
        
        for ( int j = 0; j < CHARS_PER_LINE; ++j) {
	        int idx = i  + j;
	        if ( idx >= sz )
		        break;
            fprintf( log_file, "%02x ", buffer[ idx ] );
	    }
        
	fprintf( log_file, "      ");

	for (int j = 0; j < 16; ++j) {
		int idx = i  + j;
        if ( idx > sz - 1) {
		    fprintf(log_file, " ");
		}
		else if ( buffer[ idx ] >= 32 && buffer[ idx ] <= 128) {
                     fprintf(log_file,"%c", buffer[ idx ]);
		}
		else {
                     fprintf(log_file,".");
		}
	}

        

	fprintf( log_file, "\n");
    }


}
